// C++ Templates 8.3 偏特化的执行路径选择

// 偏特化的执行路径选择是模板元编程中的一个强大技术，允许根据类型特性在编译时选择不同的代码路径。
// 这种技术结合了模板特化和SFINAE（Substitution Failure Is Not An Error）原理。

// 1. 基本概念
// 偏特化的执行路径选择允许我们：
// -根据类型特性选择最优实现
// -在编译时进行条件分支
// -避免运行时的类型检查和分支开销

// 2. 使用标签分派 (Tag Dispatching)
// 标签分派是一种基于函数重载的技术：
// 主模板
template <typename T>
void processImpl(T value, std::true_type)
{
    // 针对满足特定条件的类型的实现
    std::cout << "处理整数类型: " << value << std::endl;
}

template <typename T>
void processImpl(T value, std::false_type)
{
    // 针对不满足特定条件的类型的实现
    std::cout << "处理非整数类型" << std::endl;
}

// 公共接口
template <typename T>
void process(T value)
{
    // 根据类型特性选择实现
    // std::is_integral<T>是一个类型特性（type trait）它继承自std::integral_constant<bool, Value>
    // 对于整数类型，它继承自std::integral_constant<bool, true>（即std::true_type）
    // 对于非整数类型，它继承自std::integral_constant<bool, false>（即std::false_type）
    processImpl(value, std::is_integral<T>());
}
// 使用示例：
process(42);   // 调用 processImpl(42, std::true_type())
process(3.14); // 调用 processImpl(3.14, std::false_type())

// 3. 使用SFINAE进行路径选择
// SFINAE允许我们基于类型特性启用或禁用特定的模板实例化：
// 针对整数类型的实现
// 返回类型依赖T的时候需要家typename
template <typename T>
typename std::enable_if<std::is_integral<T>::value, void>::type
process(T value)
{
    std::cout << "整数实现: " << value << std::endl;
}

// 针对非整数类型的实现
template <typename T>
typename std::enable_if<!std::is_integral<T>::value, void>::type
process(T value)
{
    std::cout << "非整数实现" << std::endl;
}

// 4. C++11后的简化语法
// C++11引入了decltype和尾置返回类型，简化了SFINAE的使用：
// 针对整数类型的实现
template <typename T>
auto processModern(T value) ->
    typename std::enable_if<std::is_integral<T>::value, void>::type
{
    std::cout << "现代整数实现: " << value << std::endl;
}

// 针对非整数类型的实现
template <typename T>
auto processModern(T value) ->
    typename std::enable_if<!std::is_integral<T>::value, void>::type
{
    std::cout << "现代非整数实现" << std::endl;
}

// 5. C++17的if constexpr
// C++17引入了if constexpr，进一步简化了编译时条件分支：
template <typename T>
void processIfConstexpr(T value)
{
    if constexpr (std::is_integral_v<T>)
    {
        std::cout << "if constexpr整数实现: " << value << std::endl;
    }
    else
    {
        std::cout << "if constexpr非整数实现" << std::endl;
    }
}

// 6. 偏特化的高级应用
// 6.1 编译时算法优化
// 通用排序算法
template <typename Iterator, typename Enable = void>
struct SortAlgorithm
{
    static void sort(Iterator begin, Iterator end)
    {
        // 默认排序实现（如归并排序）
    }
};

// 针对随机访问迭代器的优化
template <typename Iterator>
struct SortAlgorithm<Iterator,
                     typename std::enable_if<
                         std::is_same<
                             typename std::iterator_traits<Iterator>::iterator_category,
                             std::random_access_iterator_tag>::value>::type>
{
    static void sort(Iterator begin, Iterator end)
    {
        // 快速排序实现
    }
};

// 6.2 类型特性检测
// 检测类型是否有特定成员函数
// 继承了一个std::false_type
template <typename T, typename = void>
struct HasToString : std::false_type
{
};

// template<typename... Ts>

template <typename T>
struct HasToString<T,
                   std::void_t<decltype(std::declval<T>().toString())>>
    : std::true_type
{
};

// 使用
template <typename T>
void printWithToString(const T &value)
{
    if constexpr (HasToString<T>::value)
    {
        std::cout << value.toString();
    }
    else
    {
        std::cout << "对象没有toString()方法";
    }
}

// 7. 性能考量
// 偏特化的执行路径选择在编译时完成，具有以下优势：
// 消除运行时分支预测失败的开销
// 允许编译器进行更积极的优化
// 可以生成针对特定类型高度优化的代码

// 8. 实际应用示例
// 标准库中的许多组件都使用了这种技术：
// std::vector对布尔类型的特化
// std::copy针对不同迭代器类别的优化
// std::unique_ptr的自定义删除器实现

// 偏特化的执行路径选择是模板元编程的核心技术之一，它使C++能够在不牺牲运行时性能的情况下实现高度灵活的代码。